<?php

namespace App\Services;

use App\Common\Libs\Ali\Oss;
use App\Common\Libs\ArrayHelper;
use App\Common\Libs\Dispatch\Console;
use App\Common\Libs\IdBuilder;
use App\Console\Commands\Controller\UserCommand;
use App\Consts\ExceptionCode;
use App\Consts\GlobalConsoleConst;
use App\Consts\GlobalResultCode;
use App\Consts\GlobalSmsConst;
use App\Consts\GlobalUploadConst;
use App\Consts\GlobalUserConst;
use App\Exceptions\Error;
use App\Models\Select\UserSelect;
use App\Models\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Str;

/**
 * @package App\Services
 * @see UserService
 */
class UserService extends BaseService
{
    public $_repository;
    private $_user;

    public function __construct()
    {
        parent::__construct();
        $this->_repository = repository()->UserRepository;
    }

    /**
     * 获取用户列表
     * @param $params
     * @return Builder|mixed
     */
    public function searchUserList($params)
    {
        $provider = $this->_repository->searchUserLit($params);
        $pagination = $this->getPagination();
        $list = $provider
            ->offset($pagination->pageSize * $pagination->page)
            ->limit($pagination->pageSize + 1)
            ->get();
        return self::outputMoreList($provider, $pagination, $list);
    }

    /**
     * 通过手机号新增用户
     * @param $loadData
     * @return Builder|User
     */
    public function createUserByPhone($loadData)
    {
        return $this->_repository->create($loadData);
    }

    public function createUserByOauthWx($loadData)
    {
        return $this->_repository->create($loadData);
    }

    /**
     * 修改用户信息
     * @param User $user
     * @param $loadData
     * @return bool|\Illuminate\Http\JsonResponse
     */
    public function updateUserInfo($loadData)
    {
        $user = $this->_repository->getUserByUserId($loadData['user_id']);
        if (!$user) {
            return Error::handle();
        }

        $oldAvatar = $user->avatar;

        if ($user->user_id != $loadData['id']) {
            return Error::handle();
        }

        $loadData = ArrayHelper::remove($loadData, ['id']);
        $user = $this->_repository->updateUser($user, $loadData);

        // 异步更新用户地址
        Console::getInstance(UserCommand::class)
            ->push($loadData, GlobalConsoleConst::USER_EDIT_ADDR);

        // 修改了头像，要把【文章卡片 - 推荐】区域的头像也改掉
        if (array_key_exists('avatar', $loadData)) {
            Console::getInstance(UserCommand::class)
                ->push([
                    'user_id' => $user->user_id,
                    'old_avatar' => $oldAvatar,
                    'new_avatar' => $user->avatar
                ], GlobalConsoleConst::USER_REPAIR_AVATAR);
        }

        return true;
    }

    /**
     * 修改用户信息
     * @param User $user
     * @return bool|\Illuminate\Http\JsonResponse|array
     */
    public function updateUserAvatar(User $user, $userId)
    {
        if (empty($user->user_id) || $user->user_id != $userId) {
            return Error::handle(lang('Login error'));
        }

        $oldAvatar = $user->avatar;

        // 上传资源
        $avatarUrl = Oss::getInstance(GlobalUploadConst::USER_AVATAR_PATH)
            ->uploadClientFile();
        if (!$avatarUrl) {
            return Error::handle(lang('Upload file fail'));
        }
        $loadData = [
            'avatar' => $avatarUrl,
        ];

        // 修改用户信息
        $user = $this->_repository->updateUser($user, $loadData);
        if ($user === false) {
            return Error::handle();
        }

        /**
         * 异步完成：
         *  1. 修改文章推荐列表头像区域
         */
        Console::getInstance(UserCommand::class)
            ->push([
                'user_id' => $user->user_id,
                'old_avatar' => $oldAvatar,
                'new_avatar' => $user->avatar,
            ], GlobalConsoleConst::USER_REPAIR_AVATAR);

        return ['avatar' => $avatarUrl];
    }

    /**
     * 修改手机号
     * @param User $user
     * @param $newPhone
     * @param string|int $code
     * @return bool|\Illuminate\Http\JsonResponse
     */
    public function changeUserPhone(User $user, $newPhone, $code)
    {
        if (empty($user->phone)) {
            return Error::handle(lang('User have not phone'));
        }

        // 新旧手机号一致
        if ($user->phone == $newPhone) {
            return Error::handle(lang('User have not phone'));
        }

        // 验证码校验
        $verify = service()->SmsService->checkCodeByPhoneAndTemplate($code, $newPhone, GlobalSmsConst::SMS_TEMPLATE_BIND);
        if (!$verify) {
            return Error::handle('This code is disable');
        }

        // 新手机号用户存在
        $phoneUser = $this->_repository->getUserByPhone($newPhone);
        if ($phoneUser) {
            return Error::handle('This phone already have user');
        }

        // 修改用户信息
        $updateRes = $this->_repository->updateUser($user, ['phone' => $newPhone]);
        if ($updateRes === false) {
            return Error::handle(lang('Unauthorized'));
        }

        return true;
    }

    /**
     * 修改密码
     * @param User $user
     * @param string|int $code
     * @param string $password
     * @return bool|\Illuminate\Http\JsonResponse
     */
    public function changeUserPassword(User $user, $code, $password)
    {
        $user = service()->UserService->getUserByUserId($user->user_id);
        // 手机号为空
        if (!$user || empty($user->phone)) {
            return Error::handle(lang('User have not phone'));
        }

        // 校验第一步的验证码是否正确
        $verify = service()->SmsService->checkCodeByPhoneAndTemplate($code, $user->phone, GlobalSmsConst::SMS_TEMPLATE_PASSWORD);
        if (!$verify) {
            return Error::handle('This code is disable');
        }

        // 保存密码
        $changePasswordResult = $this->_repository->changeUserPassword($user, $password);
        if ($changePasswordResult === false) {
            return Error::handle(lang('Unauthorized'));
        }

        return true;
    }

    /**
     * 获取随机昵称
     * @param string $nickname
     * @return string
     */
    public function getRandNickname($nickname = GlobalUserConst::NORMAL_USER_DEFAULT_NICKNAME): string
    {
        $rand = substr(md5(IdBuilder::getMillisecond() . Str::random()), 0, 6);

        return $nickname . $rand;
    }

    /**
     * 检测用户状态和是否有手机号
     * @param User $user
     * @return bool|\Illuminate\Http\JsonResponse
     */
    public function verifyUserStatusByUser($user)
    {
        if (empty($user->status)) {
            return Error::handle(lang('Login error'), ExceptionCode::LOGIN_FAIL, GlobalResultCode::LOGIN_USER_STATUS_DISABLE);
        }

        // 验证用户状态
        if ($user->status == GlobalUserConst::STATUS_DISABLE) {
            return Error::handle(lang('User status is disabled'));
        }

        // 验证用户是否绑定手机号
        if (!$user->phone) {
            return Error::handle(lang('User have not phone'));
        }

        return true;
    }

    /**
     * 通过用户ID获取用户
     * @param $userId
     * @param string $selectScene
     * @return mixed|User
     */
    public function getUserByUserId($userId, $selectScene = UserSelect::SELF_DETAIL)
    {
        if (empty($this->_user[$userId])) {
            if (is_numeric($userId)) {
                $user = $this->_repository->getUserById($userId, $selectScene);
            } else {
                $user = $this->_repository->getUserByUserId($userId, $selectScene);
            }
            if (!$user) {
                return false;
            }
            $this->_user[$userId] = $user;
        }

        return $this->_user[$userId];
    }

    /**
     * 通过手机号获取用户
     * @param $phone
     * @return User|object|null
     */
    public function getUserByPhone($phone)
    {
        return $this->_repository->getUserByPhone($phone);
    }

    /**
     * 通过accessToken获取用户
     * @param $accessToken
     * @return array|bool|User|null
     */
    public function getUserByAccessToken($accessToken)
    {
        $login = repository()->LoginRepository->getLoginByAccessToken($accessToken);
        if (!$login) {
            return false;
        }

        $user = $this->_repository->getUserByUserId($login->user_id, UserSelect::SELF_DETAIL);
        if (!$user) {
            return false;
        }

        return $user;
    }
}
